package com.simple.mybaits.simplemybatis.session.impl;

import com.simple.mybaits.simplemybatis.Configuration;
import com.simple.mybaits.simplemybatis.proxy.MapperProxy;
import com.simple.mybaits.simplemybatis.session.SqlSession;
import com.simple.mybaits.simplemybatis.statement.MapperStatement;
import com.simple.mybaits.simplemybatis.util.StringUtil;
import org.springframework.context.annotation.Bean;
import sun.swing.BakedArrayList;

import javax.sql.DataSource;
import java.beans.BeanDescriptor;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * @author :  zxj
 * @package :  com.simple.mybaits.simplemybatis.session.impl
 * @date :  2018/5/21
 * @description : 默认sqlsession实现
 */
public class DefalutSqlSession implements SqlSession {

    private Configuration configuration;

    private DataSource dataSource;

    public DefalutSqlSession(Configuration configuration, DataSource dataSource) {
        this.configuration = configuration;
        this.dataSource = dataSource;
    }

    @Override
    public <T> List<T> selectList(MapperStatement mapperStatement, Object[] objects) {

        List<T> result = new ArrayList<>();
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {

             connection = dataSource.getConnection();
            System.out.println(mapperStatement.getBoundSql());
             preparedStatement = connection.prepareStatement(mapperStatement.getBoundSql());
            if (objects != null) {
                for (int i = 0; i < objects.length; i++) {
                    preparedStatement.setObject(i + 1, objects[i]);
                }
            }
            resultSet = preparedStatement.executeQuery();
            Class<?> clazz = mapperStatement.getResult();

            Class<?> genericClazz = null;
            if (clazz == List.class) {
                Type type = mapperStatement.getMethod().getGenericReturnType();
                if (type == null) {
                    return null;
                }
                // 如果是泛型参数的类型
                if (type instanceof ParameterizedType) {
                    ParameterizedType pt = (ParameterizedType) type;
                    //得到泛型里的class类型对象
                    genericClazz = (Class<?>) pt.getActualTypeArguments()[0];
                }
            }

            while (resultSet.next()) {
                Object object = genericClazz.newInstance();
                BeanInfo beanInfo = Introspector.getBeanInfo(genericClazz);
                PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();

                //Write对应set()方法
                for (PropertyDescriptor propertyDescriptor : descriptors) {
                    if(propertyDescriptor.getName().equals("class")){
                        continue;
                    }
                    Method method = propertyDescriptor.getWriteMethod();

                    method.invoke(object, resultSet.getString(StringUtil.camelToUnderline(propertyDescriptor.getName())));
                }
                result.add((T) object);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                connection.close();
            }catch (Exception e){
                e.printStackTrace();
            }
            try {
                preparedStatement.close();
            }catch (Exception e){
                e.printStackTrace();
            }
            try {
                resultSet.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 查询一条记录
     *
     * @param statement
     * @param <T>
     * @return
     */
    @Override
    public <T> T selectOne(String statement) {

        return null;
    }

    /**
     * 插入一条记录
     *
     * @param
     * @return
     */
    @Override
    public int insert(String statement) {

        return 0;
    }

    /**
     * 更新一条记录
     *
     * @param id
     * @return
     */
    @Override
    public int update(String statement) {
        return 0;
    }


    /**
     * 删除一条记录
     *
     * @param id
     * @return
     */
    @Override
    public int delete(Serializable id) {
        return 0;
    }

    /**
     * 获取代理
     *
     * @param clazz
     * @param <T>
     * @return
     */
    @Override
    public <T> T getMapper(Class<?> clazz) {

        MapperProxy mapperProxy = configuration.getMapperProxyRegister().get(clazz);

        if (mapperProxy == null) {
            throw new RuntimeException("no mapperProxy found");
        }

        mapperProxy.setSqlSession(this);
        mapperProxy.setConfiguraion(configuration);

        return (T) mapperProxy.newInstance(clazz);
    }
}
